package com.sinosoft.hydra.um.services;

import com.sinosoft.hydra.um.LoginUser;
import com.sinosoft.hydra.um.condition.SearchBestProcessCondition;
import com.sinosoft.hydra.um.condition.SearchEBomCondition;
import com.sinosoft.hydra.um.condition.SearchProcessRecordCondition;
import com.sinosoft.hydra.um.condition.SearchProcessTemplateCondition;
import com.sinosoft.hydra.um.constant.BaseConstant;
import com.sinosoft.hydra.um.domain.model.LabCondition;
import com.sinosoft.hydra.um.domain.model.LabGroup;
import com.sinosoft.hydra.um.domain.permission.*;
import cn.com.sinux.spring.exception.BusinessException;
import com.sinosoft.hydra.um.helper.AuthContextHelper;
import com.sinosoft.hydra.um.repositories.*;
import cn.com.sinux.spring.utils.DateUtils;
import cn.com.sinux.spring.utils.QueryHelper;
import cn.com.sinux.spring.utils.SpecificationHelper;
import cn.com.sinux.spring.utils.ValidatorUtils;;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * Created by Administrator on 2016/7/7.
 */
@Service
@Transactional
public class SysLabService {


    @Autowired
    private ProcessManageService processManageService;
    @Autowired
    private SysEBomService eBomService;
    @Autowired
    private TProcessRecordDAO processRecordDAO;
    @Autowired
    private TProcessParameterDAO processParameterDAO;
    @Autowired
    private TExperimentalDataDAO experimentalDataDAO;
    @Autowired
    private TEBomDAO teBomDAO;
    @Autowired
    private SysParseService sysParseService;
    @Autowired
    private SysOrganizationService sysOrganizationService;

    /**
     * 查询记录
     *
     * @param searchProcessRecordCondition
     * @param pageable
     * @return
     */
    public Page<TProcessRecord> findRecords(SearchProcessRecordCondition searchProcessRecordCondition, Pageable pageable) {
        return processRecordDAO.findAll(buildSpecification(searchProcessRecordCondition), pageable);
    }

    /**
     * 获取数据
     *
     * @param searchProcessRecordCondition
     * @return
     */
    private Specification<TProcessRecord> buildSpecification(final SearchProcessRecordCondition searchProcessRecordCondition) {
        Specification<TProcessRecord> specification = SpecificationHelper.buildSpecification(new SpecificationHelper.SpecificationBuilder<TProcessRecord>() {

            public void fillParam(Root<TProcessRecord> root, CriteriaBuilder cb, List<Predicate> list) {
                if (searchProcessRecordCondition.gettProcessTemplate() != null && StringUtils.isNotBlank(searchProcessRecordCondition.gettProcessTemplate().getId())) {
                    list.add(cb.equal(root.get("tProcessTemplate").get("id").as(String.class), searchProcessRecordCondition.gettProcessTemplate().getId()));
                }
                if (StringUtils.isNotBlank(searchProcessRecordCondition.getType())) {
                    list.add(cb.equal(root.get("type").as(String.class), searchProcessRecordCondition.getType()));
                }
            }
        });
        return specification;
    }

    /**
     * 判断用户是否有权限修改历史记录
     *
     * @param loginUser
     * @param record
     * @return
     */
    public boolean hasUpdatePermission(LoginUser loginUser, TProcessRecord record) {
        if (record == null) {
            return false;
        }
        SysUserMember member = record.getCreateUser();
        if (member != null && !member.getId().equals(loginUser.getId())) {
            List<SysUserMember> leaders = sysOrganizationService.getLeaders(member.getId());
            List<String> ids = QueryHelper.doQueryProperties(leaders, true, new QueryHelper.PropertyReader<SysUserMember, String>() {

                public String read(SysUserMember sysUserMember) {
                    return sysUserMember.getId();
                }
            });
            if (!ids.contains(loginUser.getId())) {
                return false;
            }
        }
        return true;
    }

    /**
     * 修改实验记录
     *
     * @param loginUser
     * @param record
     * @return
     */
    public TProcessRecord modifyRecord(LoginUser loginUser, TProcessRecord record) {
        TProcessRecord db = processRecordDAO.findOne(record.getId());
        if (db == null) {
            throw new BusinessException("实验数据保存失败，参数不正确");
        }
        if (!hasUpdatePermission(loginUser, record)) {
            throw new BusinessException("实验数据保存失败，用户没有权限修改该数据");
        }
        record.settProcessTemplate(db.gettProcessTemplate());
        record.setType(db.getType());
        record.setOperateTime(db.getOperateTime());
        record.setResult(db.getResult());
        record.setOperator(db.getOperator());
        record.setTeBoms(db.getTeBoms());
        record.setCreateUser(db.getCreateUser());
        record.setUpdateTime(new Date());
        record.setCreateTime(db.getCreateTime());
        record.settExperimentalData(db.gettExperimentalData());

        List<TProcessParameter> processParameters = db.gettProcessParameters();
        processParameterDAO.delete(processParameters);

        processParameters = record.gettProcessParameters();
        record.settProcessParameters(null);
        record = processRecordDAO.save(record);

        //保存扩展数据
        for (TProcessParameter processParameter : processParameters) {
            processParameter.settProcessRecord(record);
        }
        processParameterDAO.save(processParameters);
        return record;
    }

    /**
     * 保存实验数据
     *
     * @param searchEBomCondition
     * @param processRecord
     * @return
     */
    public TProcessRecord saveProcessData(LoginUser loginUser, SearchEBomCondition searchEBomCondition, TProcessRecord processRecord) {
        //找到所有工件
        List<TEBom> teBoms = eBomService.findEBoms(searchEBomCondition, null).getContent();
        if (ValidatorUtils.isArrayEmpty(teBoms)) {
            throw new BusinessException("为选择进行实验的工件");
        }
        TProcessTemplate processTemplate = processManageService.findOne(processRecord.gettProcessTemplate().getId());
        if (processTemplate == null) {
            throw new BusinessException("未找到记录保存关联的模板");
        }
        List<TProcessParameter> processParameters = processRecord.gettProcessParameters();
        TExperimentalData experimentalData = processRecord.gettExperimentalData();
        //检测processRecord的各项数据是否合法
        if (ValidatorUtils.isArrayEmpty(processParameters)) {
            throw new BusinessException("未保存相关参数");
        }
        if (BaseConstant.INTEGER_TRUE.equals(processTemplate.getUseDevice())) {
            experimentalData = experimentalDataDAO.findOne(experimentalData.getId());
            if (experimentalData == null) {
                throw new BusinessException("此次实验需要相关实验数据，暂未检测到实验数据，不能保存");
            }
        }
        //开始逐个保存数据
        processRecord.setTeBoms(teBoms);
        processRecord.setCreateUser(AuthContextHelper.getLoginUser());
        processRecord.setCreateTime(new Date());
        processRecord.settProcessParameters(null);
        processRecord.settExperimentalData(null);
        processRecord.setType(BaseConstant.RecordType.RECORD_TYPE_NORMAL.name());
        processRecord = processRecordDAO.save(processRecord);

        //保存扩展数据
        for (TProcessParameter processParameter : processParameters) {
            processParameter.settProcessRecord(processRecord);
        }
        processParameterDAO.save(processParameters);

        if (experimentalData != null) {
            experimentalData.settProcessRecord(processRecord);
            experimentalDataDAO.save(experimentalData);
        }

        for (TEBom teBom : teBoms) {
            teBom.setUsed(BaseConstant.INTEGER_TRUE);
        }
        teBomDAO.save(teBoms);

        processRecord.settProcessParameters(processParameters);
        processRecord.settExperimentalData(experimentalData);
        //删除垃圾实验数据
        sysParseService.deleteUnBindExperimentalData(loginUser.getId());

        return processRecord;
    }

    /**
     * 找到单个数据记录
     *
     * @param id
     * @return
     */
    public TProcessRecord findOne(String id) {
        return StringUtils.isNotBlank(id) ? processRecordDAO.findOne(id) : null;
    }
}
